package com.atguigu.java8.stream;

import com.atguigu.java8.lambda.Employee;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.DoubleSummaryStatistics;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public class TestStreamAPI3 {

    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 9999.99, Employee.Status.FREE),
            new Employee("李四", 38, 5555.99, Employee.Status.BUSY),
            new Employee("王五", 50, 6666.66, Employee.Status.VOCATION),
            new Employee("赵六", 16, 3333.33, Employee.Status.FREE),
            new Employee("田七", 8, 7777.77, Employee.Status.BUSY)
    );

    @Test
    public void test1() {
        // allMatch：检查是否匹配所有元素
        boolean match = employees.stream().allMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(match);

        // anyMatch：检查是否至少匹配一个元素
        match = employees.stream().anyMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(match);

        // noneMatch：检查是否没有匹配所有元素
        match = employees.stream().noneMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(match);

        // findFirst：返回第一个元素
        Optional<Employee> first = employees.stream().sorted((e1, e2) -> -Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(first.get());

        // findAny：返回当前流中的任意元素
        Optional<Employee> any = employees.stream().filter(e -> e.getStatus().equals(Employee.Status.FREE))
                .findAny();
        System.out.println(any.get());
    }

    @Test
    public void test2() {
        // count：返回流中元素的总个数
        long count = employees.stream().count();
        System.out.println(count);

        // max：返回流中的最大值
        Optional<Employee> max = employees.stream()
                .max(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(max.get());

        // min：返回流中的最小值
        Optional<Double> min = employees.stream().map(Employee::getSalary)
                .min(Double::compare);
        System.out.println(min.get());
    }

    @Test
    public void test3() {
        // reduce(T identity, BinaryOperator) / reduce(BinaryOperator)：可以将流中元素反复结合起来，得到一个值
        List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Optional<Integer> reduce = integers.stream().reduce(Integer::sum);
        System.out.println(reduce.get());

        System.out.println("----------------------------------------------------");
        Optional<Double> reduce1 = employees.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(reduce1.get());
    }

    @Test
    public void test4() {
        ArrayList<Employee> arrayList = new ArrayList<>(this.employees);
        arrayList.add(new Employee("田七", 8, 7777.77, Employee.Status.BUSY));
        arrayList.add(new Employee("田七", 8, 7777.77, Employee.Status.BUSY));
        arrayList.add(new Employee("田七", 8, 7777.77, Employee.Status.BUSY));
        // collect：将流转换为其他形式。接收一个Collector接口的实现，用于给Stream中元素做汇总的方法。
        List<String> collect = arrayList.stream().map(Employee::getName).collect(Collectors.toList());
        collect.forEach(System.out::println);

        System.out.println("-----------------------------------------------------");
        Set<String> collect1 = arrayList.stream().map(Employee::getName)
                .collect(Collectors.toSet());
        collect1.forEach(System.out::println);

        System.out.println("-----------------------------------------------------");
        HashSet<String> collect2 = arrayList.stream().map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));
        collect2.forEach(System.out::println);
    }

    @Test
    public void test5() {
        // 总数
        Long counting = employees.stream().collect(Collectors.counting());
        System.out.println(counting);

        // 平均值
        Double averagingDouble = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(averagingDouble);

        // 总和
        Double summingDouble = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(summingDouble);

        // 最大值
        Optional<Employee> max = employees.stream().collect(Collectors.maxBy(Comparator.comparingDouble(Employee::getSalary)));
        System.out.println(max.get());

        // 最小值
        Optional<Double> min = employees.stream().map(Employee::getSalary).collect(Collectors.minBy(Double::compare));
        System.out.println(min.get());
    }

    @Test
    public void test6() {
        // 分组
        Map<Employee.Status, List<Employee>> statusListMap = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(statusListMap);
    }

    @Test
    public void test7() {
        // 多级分组
        Map<Employee.Status, Map<String, List<Employee>>> statusMapMap = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(e -> {
                    if (e.getAge() <= 35) {
                        return "青年";
                    } else if (e.getAge() <= 50) {
                        return "中年";
                    } else {
                        return "老年";
                    }
                })));
        System.out.println(statusMapMap);
    }

    @Test
    public void test8() {
        // 分区
        Map<Boolean, List<Employee>> listMap = employees.stream()
                .collect(Collectors.partitioningBy(e -> e.getSalary() > 8000));
        System.out.println(listMap);
    }

    @Test
    public void test9() {
        // 统计
        DoubleSummaryStatistics summaryStatistics = employees.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));

        System.out.println(summaryStatistics.getMax());
        System.out.println(summaryStatistics.getAverage());
        System.out.println(summaryStatistics.getSum());
    }

    @Test
    public void test10() {
        // 拼接字符串
        String joinName = employees.stream().map(Employee::getName)
                .collect(Collectors.joining(",", "===", "$$$"));
        System.out.println(joinName);
    }

}
